package com.power.sifa.sso;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.sso.SaSsoConsts;
import cn.dev33.satoken.sso.SaSsoHandle;
import cn.dev33.satoken.sso.SaSsoUtil;
import cn.dev33.satoken.sso.exception.SaSsoException;
import cn.dev33.satoken.sso.exception.SaSsoExceptionCode;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.plf.common.domain.ResponseDTO;
import com.plf.common.utils.JSONUtil;
import com.plf.core.base.model.Ha_manager;
import com.plf.core.base.model.Ha_role;
import com.plf.core.base.model.Ha_role_user;
import com.plf.core.base.model.Ha_user;
import com.plf.core.base.model.pageInfo.Ha_role_userPageInfo;
import com.plf.core.base.service.Ha_managerService;
import com.plf.core.base.service.Ha_menu_functionService;
import com.plf.core.base.service.Ha_roleService;
import com.plf.core.base.service.Ha_role_userService;
import com.plf.core.login.Ha_userVo;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;

/**
 * 前后台分离架构下集成SSO所需的代码 （SSO-Client端）
 */
@RestController
@Slf4j
public class H5Controller {
    private Logger logger= LoggerFactory.getLogger(this.getClass().getName());

    @Resource
    private Ha_roleService ha_roleService;

    @Resource
    private Ha_managerService ha_managerService;

    @Resource
    private Ha_menu_functionService ha_menu_functionSvc;

    @Resource
    private Ha_role_userService ha_role_userService;

    // 当前是否登录
    @RequestMapping("/isLogin")
    public Object isLogin() {
        return ResponseDTO.succData(StpUtil.isLogin());
    }

    // 返回SSO认证中心登录地址
    @RequestMapping("/getSsoAuthUrl")
    public ResponseDTO getSsoAuthUrl(String clientLoginUrl, String back) {
        String serverAuthUrl = SaSsoUtil.buildServerAuthUrl(clientLoginUrl, back);
        return ResponseDTO.succData(serverAuthUrl);
    }

    /**
     * 从SSO中心返回, 接收ticket, 验证并得到token, 返回back页
     * @return
     */
    @RequestMapping("/loginBack")
    public Object loginBack() {
        // 获取对象
        SaRequest req = SaHolder.getRequest();
        SaResponse res = SaHolder.getResponse();

        // 登录成功后前端跳转地址
        String back = req.getParam(SaSsoConsts.ParamName.back, "/");
        // 随机串 (使用一次就销毁)
        String ticket = req.getParam(SaSsoConsts.ParamName.ticket, "");

        logger.info("center 返回 ticket: {}", ticket);
        // 校验成功得到一个登录id
        Object loginId = SaSsoHandle.checkTicket(ticket, "/doLoginByTicket");
        logger.info("center 返回 loginId: {}", loginId);
        if(loginId != null) {
            StpUtil.login(loginId);
            // 通过登录id查询用户信息
            Map result = JSONUtil.json2Map((String) SaSsoUtil.getUserinfo(StpUtil.getLoginId()));
            Map<String,Object> user = (Map<String, Object>) result.get("data");

            // 构建用户对象
            Ha_userVo userVo = new Ha_userVo();
            userVo.setUserId((String) loginId);
            userVo.setAvatar((String) user.get("avatar"));
            userVo.setEmail((String) user.get("email"));
            userVo.setFullname((String) user.get("fullname"));
            userVo.setGender((Integer) user.get("gender"));
            userVo.setTelephone((String) user.get("telephone"));
            // 用户部门列表
            userVo.setDeptlist((List<Map>) user.get("deptlist"));

            Ha_role_userPageInfo pageInfo = new Ha_role_userPageInfo();
            pageInfo.setF_userid((String)loginId);
            pageInfo.setPageNumber(1);
            pageInfo.setPageSize(9999);
            List<String> roles = new ArrayList<>();
            Page<Ha_role_user> page = ha_role_userService.findAll(pageInfo);
            if (!page.isEmpty()) {
                for (Ha_role_user ha_role_user : page) {
                    roles.add(ha_role_user.getRoleid());
                }
            }
            // 用户角色列表
            userVo.setRoles(roles);


            // 存储用户后台权限列表
            List<String> permissions = null;
            // 存储用户前端权限列表
            List<String> frontPermissions = null;
            Ha_manager manager = ha_managerService.getById((String) loginId);
            if (manager != null) {
                permissions = ha_menu_functionSvc.queryPermissionList();
                frontPermissions = ha_menu_functionSvc.queryFrontPermissionList();
            } else {
                permissions =  ha_roleService.queryUserPermissionList((String) loginId);
                frontPermissions = ha_roleService.queryUserFrontPermissionList((String) loginId);
            }
            // 用户前端操作权限, 受到v-auth控制
            userVo.setPermissions(frontPermissions);

            SaSession saSession = StpUtil.getTokenSession();
            // 存入到缓存, 后端 @SaCheckPermission 注解会从中取出来校验
            saSession.set(Ha_role.PERMISSION, permissions);
            saSession.set(Ha_user.USER, userVo);

            saSession.update();
        }else{
            throw new SaSsoException("无效ticket：" + ticket).setCode(SaSsoExceptionCode.CODE_20004);
        }
        // 生成token拼接到返回url后面
        return res.redirect(fixBackUrl(back));
    }

    /**
     * 整理返回地址, 增加token参数值
     * @return
     */
    private String fixBackUrl(String url) {
        Map<String, String> backParams=new HashMap<String, String>();
        int qm_idx=url.indexOf("?");
        String prefix=url;
        if (qm_idx != -1) {
            prefix=url.substring(0, qm_idx);
            String[] pars=url.substring(qm_idx+1).split("&");
            for(String pa : pars){
                String[] paitem=pa.split("=");
                backParams.put(paitem[0], paitem[1]);
            }
        }
        backParams.put(StpUtil.getTokenName(), StpUtil.getTokenValue());
        StringBuilder reurl = new StringBuilder(prefix);
        reurl.append("?");

        Iterator<String> keyit=backParams.keySet().iterator();
        while(keyit.hasNext()){
            String key=keyit.next();
            String val=backParams.get(key);
            reurl.append(key);
            reurl.append("=");
            reurl.append(val);
            reurl.append("&");
        }

        return reurl.toString();
    }

    // 根据ticket进行登录
    @RequestMapping("/doLoginByTicket")
    public ResponseDTO doLoginByTicket(String ticket) {
//        logger.info("ticket: {}", ticket);
        Object loginId = SaSsoHandle.checkTicket(ticket, "/doLoginByTicket");
//        logger.info("loginId: {}", loginId);
        if(loginId != null) {
            StpUtil.login(loginId);
            Map result = JSONUtil.json2Map((String) SaSsoUtil.getUserinfo(StpUtil.getLoginId()));
            Map<String,Object> user = (Map<String, Object>) result.get("data");

            Ha_userVo userVo = new Ha_userVo();
            userVo.setUserId((String) loginId);
            userVo.setAvatar((String) user.get("avatar"));
            userVo.setEmail((String) user.get("email"));
            userVo.setFullname((String) user.get("fullname"));
            userVo.setGender((Integer) user.get("gender"));
            userVo.setTelephone((String) user.get("telephone"));
            userVo.setDeptlist((List<Map>) user.get("deptlist"));

            Ha_role_userPageInfo pageInfo = new Ha_role_userPageInfo();
            pageInfo.setF_userid((String)loginId);
            List<String> roles = new ArrayList<>();
            Page<Ha_role_user> page = ha_role_userService.findAll(pageInfo);
            if (!page.isEmpty()) {
                for (Ha_role_user ha_role_user : page) {
                    roles.add(ha_role_user.getRoleid());
                }
            }
            userVo.setRoles(roles);

            // 查询用户后台权限列表
            List<String> permissions = ha_roleService.queryUserPermissionList((String) loginId);

            // 查询用户前端权限列表
            List<String> frontPermissions = ha_roleService.queryUserFrontPermissionList((String) loginId);
            userVo.setPermissions(frontPermissions);

            SaSession saSession = StpUtil.getTokenSession();
            saSession.set(Ha_role.PERMISSION, permissions);
            saSession.set(Ha_user.USER, userVo);

            saSession.update();
            return ResponseDTO.succData(StpUtil.getTokenValue());
        }
        return ResponseDTO.succMsg("无效ticket：" + ticket);
    }

	// 查询我的账号信息
	@RequestMapping("/myinfo")
	public Object myinfo() {
        SaSession saSession = StpUtil.getTokenSession();
        Ha_userVo user = saSession.getModel(Ha_user.USER, Ha_userVo.class);
		return ResponseDTO.succData(user);
	}

    /**
     * 退出登录
     * @return
     */
	@PostMapping("/logout")
	public ResponseDTO logout() {
    	String token=StpUtil.getTokenValue();
		log.info("退出登录 token={}", token);
        StpUtil.logoutByTokenValue(token);
        return ResponseDTO.succ();
    }

    // 全局异常拦截
    @ExceptionHandler
    public SaResult handlerException(Exception e) {
        e.printStackTrace();
        return SaResult.error(e.getMessage());
    }

}
